var Vector = function(point) {
    if (point === undefined) {
        this.x = 0;
        this.y = 0;
    }
    else {
        this.x = point.x;
        this.y = point.y;
    }
};

Vector.prototype = {
    getMagnitude: function() {
        return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2))
    },

    add: function(vector) {
        var v = new Vector();
        v.x = this.x + vector.x;
        v.y = this.y + vector.y;
        return v
    },

    subtract: function(vector) {
        var v = new Vector();
        v.x = this.x - vector.x;
        v.y = this.y - vector.y;
        return v
    },

    dotProduct: function(vector) {
        return this.x * vector.x + this.y * vector.y
    },

    // 由两点生成边
    edge: function(vector) {
        return this.subtract(vector)
    },

    // 垂直，即投影轴
    perpendicular: function() {
        var v = new Vector();
        v.x = this.y;
        v.y = 0 - this.x;
        return v
    },

    normalize: function() {
        var v = new Vector(0, 0),
                m = this.getMagnitude();

        if(m !== 0) {
            v.x = this.x / m;
            v.y = this.y /m;
        }
        return v
    },

    normal: function() {
        var p = this.perpendicular();
        return p.normalize();
    }
};

var Projection = function(min, max) {
    this.min = min;
    this.max = max;
};

Projection.prototype = {
    overlaps: function(projection) {
        return this.max > projection.min && projection.max > this.min;
    }
};

module.exports = function(){
    this.getPivotPoint = function(sp){
        return {
            x:sp.x+sp.pivot.x*sp.width,
            y:sp.y+sp.pivot.y*sp.height
        }
    };
    this.getPivotLocal = function(sp){
        var pivotPoint ={
            x:sp.x+sp.pivot.x*sp.width,
            y:sp.y+sp.pivot.y*sp.height
        };
        var localPoint = {x:sp.x -pivotPoint.x,y:sp.y-pivotPoint.y};
        return localPoint;
    };
    this.getRotatePoint = function(sp){
        var getRotatePoint = this.getPivotPoint(sp);
        var newRotate = ((sp.angle%360)+360)%360;
        var rotatePoint = {
            x: (sp.x-getRotatePoint.x)*Math.cos(newRotate/180*Math.PI) - (sp.y-getRotatePoint.y)*Math.sin(newRotate/180*Math.PI)+getRotatePoint.x,
            y: (sp.x-getRotatePoint.x)*Math.sin(newRotate/180*Math.PI) + (sp.y-getRotatePoint.y)*Math.cos(newRotate/180*Math.PI)+getRotatePoint.y
        };
        return rotatePoint;
    };
    this.getRotatePoint2 = function(p1,p2,angle){
        var getRotatePoint = p1;
        var newRotate = ((angle%360)+360)%360;
        var rotatePoint = {
            x: (p2.x-getRotatePoint.x)*Math.cos(newRotate/180*Math.PI) - (p2.y-getRotatePoint.y)*Math.sin(newRotate/180*Math.PI)+getRotatePoint.x,
            y: (p2.x-getRotatePoint.x)*Math.sin(newRotate/180*Math.PI) + (p2.y-getRotatePoint.y)*Math.cos(newRotate/180*Math.PI)+getRotatePoint.y
        };
        return rotatePoint;
    };
    this.polarCoordinates=function(point,angle,distance){
        angle=(angle%360+360)%360;
        var p2={x:0,y:0};
        if(angle>0&&angle<90){
            p2.x=point.x+Math.cos(angle*2*Math.PI/360)*distance;
            p2.y=point.y+Math.sin(angle*2*Math.PI/360)*distance;
        }else if(angle>90&&angle<180){
            p2.x=point.x-Math.sin((angle-90)*2*Math.PI/360)*distance;
            p2.y=point.y+Math.cos((angle-90)*2*Math.PI/360)*distance;
        }else if(angle>180&&angle<270){
            p2.x=point.x-Math.cos((angle-180)*2*Math.PI/360)*distance;
            p2.y=point.y-Math.sin((angle-180)*2*Math.PI/360)*distance;
        }else if(angle>270&&angle<360){
            p2.x=point.x+Math.sin((angle-270)*2*Math.PI/360)*distance;
            p2.y=point.y-Math.cos((angle-270)*2*Math.PI/360)*distance;
        }
        if(angle==0||angle==360){
            p2.x=point.x+distance;
            p2.y=point.y;
        }else if(angle==90){
            p2.x=point.x;
            p2.y=point.y+distance;
        }else if(angle==180){
            p2.x=point.x-distance;
            p2.y=point.y;
        }else if(angle==270){
            p2.x=point.x;
            p2.y=point.y-distance;
        }
        return p2;
    };
    this.getRotatePoints = function(sp){
        var arr = [];
        arr.push(this.getRotatePoint(sp));
        arr.push(this.polarCoordinates(arr[0],sp.angle,sp.width));
        arr.push(this.polarCoordinates(arr[1],sp.angle+90,sp.height));
        arr.push(this.polarCoordinates(arr[0],sp.angle+90,sp.height));
        return arr;
    };
    this.pointToVec = function(vecs){
        var returnArr = [];
        var len = vecs.length-1;

        for(var i =0;i<len;i++){
            var v1 = new Vector(vecs[i]);
            var v2 = new Vector(vecs[i+1]);
            returnArr.push(v1.edge(v2).normalize());
        }
        var v1 = new Vector(vecs[vecs.length-1]);
        var v2 = new Vector(vecs[0]);
        returnArr.push(v1.edge(v2).normalize());
        return returnArr;
    };
    this.getP = function(axis,points){
        var scalars = [],
                    v = new Vector();
        points.forEach(function(point) {
            v.x = point.x;
            v.y = point.y;
            scalars.push(v.dotProduct(axis))
        });

        return new Projection(Math.min.apply(Math, scalars),
                Math.max.apply(Math, scalars))
    },
    this.getBoundingSprite = function(node){
        return {
            angle : -node.rotation,
            pivot : {x:node.anchorX,y:node.anchorY},
            x : node.x-node.anchorX*node.width,
            y : node.y-node.anchorY*node.height,
            width : node.width,
            height : node.height
          }
    },
    this.obb = function(sp1,sp2){
        var pointArr1 = this.getRotatePoints(sp1);
        var pointArr2 = this.getRotatePoints(sp2);
        var vec1 = this.pointToVec(pointArr1);
        var vec2 = this.pointToVec(pointArr2);
        var allVec = vec1.concat(vec2);
        var len = allVec.length-1;
        for(var i=0;i<len;i++){
            var axis = allVec[i];
            var p1 = this.getP(axis,pointArr1);
            var p2 =  this.getP(axis,pointArr2);
            if(!p1.overlaps(p2)){
                return false;
            }
        }
        return true;
    };
}